import unittest
from pyurl.url import URL
from pyurl.protocols.zip import ZipURL

class TestURL(unittest.TestCase):
    def test_creation(self):
        self.assertEqual(str(URL("file:/some/path")), "file:/some/path")
        self.assertEqual(str(URL("http://test.de/some/path")), "http://test.de/some/path")
        self.assertEqual(str(URL(URL("http://user:test@test.de/some/path"))), "http://user:test@test.de/some/path")
        
    def test_path_creation(self):
        self.assertEqual(str(URL("/some/path")), "/some/path")
        self.assertEqual(str(URL(URL("some/path"))), "some/path")
          
    def test_authority_extraction(self):
        url = URL("http://d:c@newhost.de:8080/testfolder")
        self.assertEqual(url.username, "d")
        self.assertEqual(url.hostname, "newhost.de")
        self.assertEqual(url.password, "c")
        self.assertEqual(url.port, 8080)
                
    def test_url_editing(self):
        url = URL("http:")
        self.assertEqual(str(url), "http:.")

        url.authority = "a:b@test.de"
        self.assertEqual(str(url), "http://a:b@test.de")
        
        url.password = "c"
        self.assertEqual(str(url), "http://a:c@test.de")
        
        url.username = "d"
        self.assertEqual(str(url), "http://d:c@test.de")
        
        url.hostname = "newhost.de"
        self.assertEqual(str(url), "http://d:c@newhost.de")
        
        url.port = 8080
        self.assertEqual(str(url), "http://d:c@newhost.de:8080")
        
        url.path = "testfolder"
        self.assertEqual(str(url), "http://d:c@newhost.de:8080/testfolder")

        url = URL("http:")     
        self.assertRaises(AttributeError, setattr, url, "scheme", "test")   
        self.assertRaises(AttributeError, setattr, url, "username", "test")
        self.assertRaises(AttributeError, setattr, url, "password", "test")
        self.assertRaises(AttributeError, setattr, url, "port", "test")
        
        url.hostname = "test.de"

        self.assertRaises(AttributeError, setattr, url, "scheme", "test")   
        self.assertRaises(AttributeError, setattr, url, "password", "test")
        
        url.username = "test"
        self.assertRaises(AttributeError, setattr, url, "scheme", "test")   
        
    def test_path_joining(self):
        parentPath = URL("/some/path")
        
        path = URL(parentPath, "child")
        self.assertEqual(str(path), "/some/path/child")

        path3 = URL(parentPath, "/root_folder")
        self.assertEqual(str(path3), "/root_folder")
        
        path4 = URL("http://test.de/some/parent", "/root_folder")
        self.assertEqual(str(path4), "http://test.de/root_folder")
        
    def test_url_path_joining(self):
        parentPath = URL("/some/path")
        
        path = URL(parentPath, URL("child"))
        self.assertEqual(str(path), "/some/path/child")

        path3 = URL(parentPath, URL("/root_folder"))
        self.assertEqual(str(path3), "/root_folder")
        
        path4 = URL("http://test.de/some/parent", URL("/root_folder"))
        self.assertEqual(str(path4), "http://test.de/root_folder")
        
    def test_url_parents(self):
        root = URL("/")
        parent_path = root / "/some_path"
        self.assertEqual(parent_path.parent, root)
        
        path = parent_path / "child"
        self.assertEqual(path.parent, parent_path)

        self.assertEqual(root.parent, root)
        
    def test_invalid_constructor_call(self):
        self.assertRaises(ValueError, URL, None)
        self.assertRaises(ValueError, URL, [])
        self.assertRaises(ValueError, URL, "/", [])
        
    def test_equality(self):
        self.assertEqual(URL("/some/path"), URL("/some/path"))
        self.assertEqual(URL("file:/some/path"), "file:/some/path")
        self.assertEqual(URL("/some/path", "child"), URL("/some/path/child"))
    
    def test_join_operator(self):
        parent = URL("/some/path")
        self.assertEqual(parent/"child", URL(parent, "child"))
        self.assertRaises(ValueError, lambda: URL("/") / [])
        
    def test_url_paths(self):
        self.assertEqual(URL("http://test.de/", "test.txt"), "http://test.de/test.txt")
        
    def test_scheme_extraction(self):
        self.assertEqual(URL("http://test.de/test.txt").scheme, "http")
        self.assertEqual(URL("test.txt").scheme, "path")
        self.assertEqual(URL("some/completly://broken.url").scheme, "path")
     
    def test_parameter_extraction(self):
        parameter = {"a": "a_value", "b": "b_value"}
        url = URL("http://test.de/?a=a_value&b=b_value")
        self.assertEqual(url.parameter, parameter)

    def test_parameter_reconstruction(self):
        url = URL("http://test.de/?a=a_value&b=b_value")
        self.assertEqual(str(url), "http://test.de/?a=a_value&b=b_value")
        
        
class TestArchiveURLManipulation(unittest.TestCase):
    def test_creation(self):
        archive_path = URL("http://test.de/test.zip")
        url = URL("zip:")
        url.archive = archive_path
        url.path = "test.txt"
        
        url2 = URL("zip:")
        url2.archive = "http://test.de/test.zip"
        url2.path = "test.txt"
        
        url3 = URL("zip:http://test.de/test.zip!test.txt")
        
        self.assertEqual(url, url2)
        self.assertEqual(url2, url3)
        self.assertEqual(url, "zip:http://test.de/test.zip!test.txt")
        
    def test_path_manipulation(self):
        url = URL("zip:http://test.de/test.zip!/test")
        self.assertEqual(url / "test.txt", "zip:http://test.de/test.zip!/test/test.txt")
    
    def test_url_parents(self):
        url = URL("zip:http://test.de/test.zip!/test/test.txt")
        self.assertEqual(url.parent, "zip:http://test.de/test.zip!/test")
        self.assertEqual(url.parent.parent, "zip:http://test.de/test.zip!/")
        self.assertEqual(url.parent.parent.parent, "http://test.de/test.zip")
        

def suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestURL))
    suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestArchiveURLManipulation))
    return suite

